//
// Created by Administrator on 2015/5/22.
//

#pragma once

#include <stdint.h>
#include <cstring>
#include <stdio.h>
#if !defined(__MINGW32__)  && !defined(__MINGW64__)
#include <thread>
#endif
#include "es.h"

#if defined(__linux__) || defined(__MINGW32__) || defined(__APPLE__)
#include <sys/time.h>
#else
#include <time.h>
#endif

#if defined(__ESVR_WIN32__) || defined(_MSC_VER)
#define snprintf _snprintf
#endif

namespace esvr
{
    static inline time_t get_curr_time()
    {
        return time(NULL);
    }

    template <typename T>
    static inline T get_time_of_day(T& time)
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        if(sizeof(T) > sizeof(uint32_t))
        {
            time = tv.tv_sec + tv.tv_usec * 1e6;
        }
        else
        {
            time = tv.tv_sec;
        }
       return time;
    }

    static inline std::string get_current_datetime_str()
    {
        time_t t_now = time(NULL);
        struct tm now = *localtime(&t_now);
        char buffer[64] = {0};
        snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d", now.tm_year+1900, now.tm_mon+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec);
        return buffer;
    }

    static inline uint32_t get_cpu_core_count()
    {
        #if defined(__MINGW32__) || defined(__MINGW64__)
        return 1;
        #else
        return std::thread::hardware_concurrency();
        #endif
    }

    const static size_t lfq_max_size = 2048;

    template<typename T>
    class LockFreeQueue
    {
    private:
        T m_data[lfq_max_size];
        volatile size_t m_head, m_tail;

    public:
        LockFreeQueue() noexcept :m_head(0), m_tail(0)
        {

        }

        void push(const T& item)
        {
            m_data[m_tail] = item;
            m_tail = (m_tail + 1) % lfq_max_size;
        }

        T* pop()
        {
            if(m_head == m_tail) return NULL;
            T* result = &m_data[m_head++];
            m_head %= lfq_max_size;
            return  result;
        }

        bool is_full() const noexcept
        {
            return (m_tail + 1) % lfq_max_size == m_head;
        }

        bool is_empty() const noexcept
        {
            return m_head == m_tail;
        }

    };
};
